package com.vst.orm.base;


import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import static com.google.common.base.Objects.firstNonNull;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;

import org.hibernate.Session;
import org.springframework.transaction.annotation.Transactional;

import com.vst.orm.base.impl.QueryImpl;
import com.vst.orm.util.Generics;
import com.vst.orm.util.StringUtil;



/**
 * Base Entity Persistence Service Support.
 */
@Transactional
public class BaseManager<T, ID extends Serializable> implements Manager<T, ID> {
	private static final String PROPERTY_NAME = "name";

	private Class<T> _persistentClass;

	private Hibernatify hibernatify;

	
	public BaseManager() {
	}

	@Inject
	public void setHibernatify(Hibernatify hibernatify) {
		this.hibernatify = hibernatify;
	}

	public BaseManager(Hibernatify hibernatify, Class<T> persistentClass) {
		this.hibernatify = hibernatify;
		this._persistentClass = checkNotNull(persistentClass);
	}

	@Transactional(readOnly = true)
	public T get(ID id) {
		return hibernatify.get(getEntityClass(), id);
	}

	@Transactional(readOnly = true)
	public T getOrElse(ID id, T that) {
		final T result = find(id);
		return firstNonNull(result, that);
	}

	@Transactional
	public T save(T entity) {
		return hibernatify.put(entity);
	}

	@Transactional
	public List<T> save(T entity, T... rest) {
		return hibernatify.put(entity, rest);
	}

	@Transactional
	public List<T> save(T[] entities) {
		return hibernatify.put(Arrays.asList(entities));
	}

	@Transactional
	public T update(T entity) {
		return hibernatify.put(entity);
	}

	@Transactional
	public List<T> update(T entity, T... rest) {
		return hibernatify.put(entity, rest);
	}

	@Transactional
	public List<T> update(T[] entities) {
		return hibernatify.put(Arrays.asList(entities));
	}

	@Transactional
	public void delete(T entity) {
		hibernatify.delete(entity);
	}

	@Transactional
	public void delete(T entity, T... rest) {
		hibernatify.delete(entity, rest);
	}

	@Transactional
	public void delete(T[] entities) {
		hibernatify.delete(Arrays.asList(entities));
	}

	@Transactional
	public void deleteById(ID id) {
		hibernatify.delete(getEntityClass(), id);
	}

	@Transactional
	public void deleteById(ID id, ID... rest) {
		hibernatify.delete(getEntityClass(), id, rest);
	}

	@Transactional
	public void deleteById(ID[] ids) {
		hibernatify.delete(getEntityClass(), Arrays.asList(ids));
	}

	@Transactional(readOnly = true)
	public int count() {
		return hibernatify.count(getEntityClass());
	}

	@Transactional(readOnly = true)
	public List<T> findAll() {
		return hibernatify.find(getEntityClass());
	}

	@Transactional(readOnly = true)
	public Page<T> findPage() {
		return query().page(1, Integer.MAX_VALUE).page();
	}

	@Transactional(readOnly = true)
	public T find(ID id) {
		return hibernatify.find(getEntityClass(), id);
	}

	@Transactional(readOnly = true)
	public List<T> findByProperty(String name, Object value) {
		if(!StringUtil.isValid(value)||!StringUtil.isValid(name))
		{
			return null;
		}
		return query().filterEqual(name, value).list();
	}

	@Transactional(readOnly = true)
	public T findUniqueByProperty(String name, Object value) {
		if(!StringUtil.isValid(value)||!StringUtil.isValid(name))
		{
			return null;
		}
		return query().filterEqual(name, value).unique();
	}

	@Transactional(readOnly = true)
	public List<T> findByName(Object value) {
		return findByProperty(PROPERTY_NAME, value);
	}

	@Transactional(readOnly = true)
	public T findUniqueByName(Object value) {
		return findUniqueByProperty(PROPERTY_NAME, value);
	}

	@Transactional(readOnly = true)
	public <RT> RT unique(Query<T, RT> query) {
		return hibernatify.unique(query);
	}

	@Transactional(readOnly = true)
	public <RT> List<RT> list(Query<T, RT> query) {
		return hibernatify.list(query);
	}

	@Transactional(readOnly = true)
	public <RT> Page<RT> page(Query<T, RT> query) {
		return hibernatify.page(query);
	}

	@Transactional(readOnly = true)
	public <RT> int count(Query<T, RT> query) {
		return hibernatify.count(query);
	}

	@Transactional(readOnly = true)
	public Query<T, T> query() {
		return new QueryImpl<T, T>(this);
	}

	@Transactional(readOnly = true)
	public <RT> Query<T, RT> query(Class<RT> resultClass) {
		return new QueryImpl<T, RT>(this);
	}

	@SuppressWarnings("unchecked")
	public Class<T> getEntityClass() {
		if (_persistentClass == null) {
			try {
				_persistentClass = (Class<T>) Generics.getTypeParameterClass(this.getClass());
			} catch (Exception e) {
				throw new RuntimeException("无法获取实体类型", e);
			}
		}
		return checkNotNull(_persistentClass, "无法获取实体类型");
	}

	protected Session getSession() {
		return hibernatify.getSession();
	}
	
	public List queryResultBySQL(String sql) throws Exception
	{
		Session session = this.getSession();
		org.hibernate.Query query = session.createSQLQuery(sql);
		if(null == query)
		{
			return null;
		}
		List list = query.list();
		return list;
	}
	
	/*
	public Page_s queryResultBySQL(Page_s page_s) throws Exception
	{
		List count = queryResultBySQL(page_s.getCountSql());
		if(null != count && !count.isEmpty())
		{
			//设置总记录数
			page_s.setTotalCount(Integer.parseInt(count.get(0).toString()));
			//设置分页后的结果集
			page_s.setResult(queryResultBySQL(page_s.getPageSql()));
		}
		return page_s;
	}*/

}
